#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "wget.h"
#include "log.h"
#include "http.h"
#include "progress.h"


int wget(http_url *url, const char *filename) {
    // create
    int sockfd = 0;

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        exit(1);
    }

    // connect
    struct sockaddr_in servaddr;
    servaddr.sin_family = AF_INET;
    servaddr.sin_port   = htons(url->port);

    if (inet_pton(AF_INET, url->ip, &servaddr.sin_addr) < 0) {
        exit(1);
    }

    if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
        exit(1);
    }

    // write
    char *http_request = create_http_request(url);

    if (write(sockfd, http_request, strlen(http_request)) < 0) {
        exit(1);
    }

    // read
    int buf_size      = 128;
    int response_size = buf_size * 4;
    int len           = 0;
    int header_length = 0;

    char response_buf[buf_size];
    memset(response_buf, 0, buf_size);

    char *response = (char *) malloc(response_size);
    memset(response, 0, response_size);

    int  download_size = 0;
    int  fd            = open(filename, O_CREAT | O_WRONLY, 0777);
    bool is_header     = true;

    http_response_header *http_res = NULL;

    while ((len = read(sockfd, response_buf, buf_size)) > 0) {

        if (is_header) {
            if (header_length + len >= response_size) {
                response_size *= 2;
                char *response_new = (char *) realloc(response, response_size);

                if (!response_new) { error_log("realloc error\n");
                    exit(1);
                }

                if (response_new != response) {
                    free(response);
                    response = response_new;
                }
            }

            response_buf[len] = '\0';
            strcat(response, response_buf);
            header_length += len;

            char *header_end = strstr(response, "\r\n\r\n");

            if (header_end) {
                header_length = header_end - response;
                http_res = http_response_header_prase(response, header_length);

                download_size += strlen(response) - header_length - 4;
                write(fd, header_end + 4, download_size);
                download_progress(download_size,http_res->content_length);

                int offset = strlen(response_buf);

                char *padding     = response_buf + offset;
                int  padding_size = len - offset;

                write(fd, padding, padding_size);

                download_size += padding_size;
                download_progress(download_size,http_res->content_length);

                is_header = false;
            }

        } else {
            download_size += len;
            write(fd, response_buf, len);
            download_progress(download_size,http_res->content_length);
        }

    }

    printf("\n下载长度:%d\n", download_size);

    // close 
    close(sockfd);
    close(fd);

    free(http_request);
    free(http_res);
    free(response);

    return 0;
}
